﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Moki.Examples.Model;
using System.IO;
using System.Xml;

namespace Moki.Examples
{
    [TestFixture]
    public class MokiSpecify
    {
        [TearDown]
        public static void TearDown()
        {
            Mock.CleanUp();
        }

        [Test]
        public static void DefaultPropertyBehavior()
        {
            IPerson person = Mock.Create<IPerson>();

            person.Name = "Zuzia";

            Assert.AreEqual("Zuzia", person.Name);
        }

        [Test]
        public static void CustomBehavior()
        {
            // Arrange
            IBookingDB database = Mock.Create<IBookingDB>();
            CinemaBookingService bookingService = new CinemaBookingService(database);

            Show show = new Show();
           
            Mock.WhenCalled(() => database.GetBooking(show, 10)).
                Do(args =>
                {
                    if (((Show)args[0]).RoomNumber == 1)
                        return new Booking() { bookedDate = DateTime.Now } ;
                    else
                        return null;
                });

            // Act
            show.RoomNumber = 1;
            bookingService.CancelBooking(show, 10); // should not fail because show.RooNumber == 1

            show.RoomNumber = 2;
            // bookingService.CancelBooking(show, 10);  // should fail...
        }


        [Test]
        [ExpectedException(ExpectedException=typeof(BookingException))]
        public static void ThrowsException()
        {
            // Arrange
            IBookingDB database = Mock.Create<IBookingDB>();
            CinemaBookingService booking = new CinemaBookingService(database);

            Show show = new Show();

            Mock.WhenCalled(() => database.Book(show, 10, "Jan Kowalski")).
                Throws(new BookingException());

            // Act
            booking.BookPlace(show, 10, "Jan Kowalski"); // should throws booking exception

        }

        [Test]
        public static void Callback()
        {
            // Arrange
            IBookingDB database = Mock.Create<IBookingDB>();
            CinemaBookingService bookingService = new CinemaBookingService(database);

            Show show = new Show();
            bool booked = false;

            Mock.WhenCalled(() => database.Book(show, 10, "Jan Kowalski")).
                Callback(() => booked = true);

            // Act
            bookingService.BookPlace(show, 10, "Jan Kowalski");

            // Assert
            Assert.IsTrue(booked);
        }


        [Test]
        public static void ConsecutiveCalls()
        {
            Random rand = Mock.Create<Random>();

            Mock.WhenCalled(() => rand.Next()).Returns(1, 2, 3);

            Assert.AreEqual(1, rand.Next());
            Assert.AreEqual(2, rand.Next());
            Assert.AreEqual(3, rand.Next());
            Assert.AreEqual(3, rand.Next());
        }

        [Test]
        public static void ConsecutiveCallsWithCallbacks()
        {
            string path = @"We_dont_need_test_file.csv";

            CsvReader reader = Mock.Create<CsvReader>(path);

            Mock.WhenCalled(() => reader.ReadLine())
                .Returns("1; Test-Driven development by example; Kent Beck;")
                .Returns("2; Test-Driven Development: A Practical Guide; David Astels;")
                .Returns("3; xUnit Test patterns; Gerard Meszaros;")
                    .Callback(() => reader.EndOfStream = true);

          
            Assert.AreEqual(false, reader.EndOfStream);
            
            Assert.AreEqual("1; Test-Driven development by example; Kent Beck;",
                reader.ReadLine());
            Assert.AreEqual("2; Test-Driven Development: A Practical Guide; David Astels;", 
                reader.ReadLine());
            Assert.AreEqual("3; xUnit Test patterns; Gerard Meszaros;",
                reader.ReadLine());

            Assert.AreEqual(true, reader.EndOfStream);

        }
    }
}

